#!/usr/bin/env node

/**
 * 目录初始化模块
 * @module help
 * @author 夏皆成
 */

var shell = require("shelljs");
var argv = require('yargs').argv;
var path = require('path');
var fs = require('fs');
var colors = require('colors');
var readline = require('readline');

var help = exports;


help.defaultCfg = {
    targetDir: null,
    templDir: null
}


/**
 * 初始化模块
 * @param  {Object} cfg 配置对象
 */
help.init = function(cfg) {
    var self = this;
    cfg = this._cfg = self.defaultCfg;

    // 获取目标目录
    cfg.targetDir = shell.exec('pwd').output.trim();

    // 获取模板目录
    cfg.templDir = path.join(__dirname, 'template');

    self.useit();

}

help.useit = function() {
    var self = this,
        cfg = this._cfg;

    // 获取目录类型
    var dirtype = process.argv[2];

    // 根据目录类型进行处理
    if (dirtype === 'plug') {
        var plugname = argv.plugname;
        if (!plugname) {
            // console.log(colors.red('error: 请指定插件名称'), ' --plugname someplug');
            // return;
            // 提示用户输入
            var rl = self.initReadline();
            rl.question('请输入插件名称：',function(answer){
                plugname = answer;
                var pluginfo = {
                    plugname: plugname
                }
                rl.close();
                self.createPlugDir(pluginfo);
            })
        }
        return;
    }

    if (dirtype === 'clean') {
        self.clean();
        return;
    }

    console.log(colors.red('请指定目录类型'));
}

help.initReadline = function(){
    var self = this,
        cfg = this._cfg;
    
    
    return readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });
}

/**
 * 创建插件目录
 * @param  {String} pluginfo 插件的信息
 */
help.createPlugDir = function(pluginfo) {
    var self = this,
        cfg = this._cfg;

    // 默认模板数据
    var defaultPluginfo = {
        plugname: 'yourplugname',
        author: 'yourname',
        plugnameNoPrefix: 'plugname'
    }

    pluginfo = self.extend({}, defaultPluginfo, pluginfo);

    var tmplDir = path.join(cfg.templDir, 'simple-plug/');

    // 取出插件名的jquery前缀
    var hasJqueryPrefix = pluginfo.plugname.match(/^jquery./);

    // 为插件信息添加无jquery前缀的模块名
    if(hasJqueryPrefix) {
        pluginfo.plugnameNoPrefix = pluginfo.plugname.replace(/^jquery./,'');
    }

    // 将目录复制到目标目录
    shell.exec('cp -r ' + tmplDir + ' ' + cfg.targetDir.trim(), function() {

        var filesNeedReplace = ['package.json'];

        if (hasJqueryPrefix) {
            filesNeedReplace.push('jquery.plugname.js');
        } else {
            filesNeedReplace.push('plugname.js')
        }

        // 替换文件中的字符串
        filesNeedReplace.forEach(function(filename, index) {
            // 为文件名加上目标路径
            filename = path.join(cfg.targetDir.trim(), filename);
            // 对替换文件进行替换
            self.throughFile(filename, function(data) {
                return data.replace(/{{(\w+)}}/g, function($$, $1) {
                    var value = pluginfo[$1];
                    if (!value) {
                        console.log(colors.red('模板数据中缺少字段', $1));
                        return;
                    }
                    return value;
                });
            })

        })

        // 替换文件名
        if (hasJqueryPrefix) {
            shell.exec('rm plugname.js');
            shell.exec('mv jquery.plugname.js ' + pluginfo.plugname + '.js');
        } else {
            shell.exec('rm jquery.plugname.js');
            shell.exec('mv plugname.js ' + pluginfo.plugname + '.js');
        }
        console.log('目录初始化成功！')
    });
}

/**
 * 清理当前目录
 */
help.clean = function() {
    var self = this,
        cfg = this._cfg;

    shell.exec('rm -r ' + path.join(cfg.targetDir, '/*'));
}

/**
 * 提示错误信息
 * @param  {String} message 错误信息
 */
help.err = function(message) {
    console.log(colors.red(message));
}

/**
 * 处理文件的内容
 * @param  {String}   filename 文件名
 * @param  {Function} callback 用来处理文件的回调函数
 *                             参数为文件的原始数据，返回的是文件处理后的数据
 */
help.throughFile = function(filename, callback) {
    if (!callback) return;
    var originData = fs.readFileSync(filename, {
        encoding: 'utf8'
    });

    var afterData = callback(originData);

    fs.writeFileSync(filename, afterData);
}

help.extend = function() {
    var options, name, src, copy, copyIsArray, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;

    // Handle a deep copy situation
    if (typeof target === "boolean") {
        deep = target;
        target = arguments[1] || {};
        // skip the boolean and the target
        i = 2;
    }

    // Handle case when target is a string or something (possible in deep copy)
    if (typeof target !== "object" && !jQuery.isFunction(target)) {
        target = {};
    }

    // extend jQuery itself if only one argument is passed
    if (length === i) {
        target = this;
        --i;
    }

    for (; i < length; i++) {
        // Only deal with non-null/undefined values
        if ((options = arguments[i]) != null) {
            // Extend the base object
            for (name in options) {
                src = target[name];
                copy = options[name];

                // Prevent never-ending loop
                if (target === copy) {
                    continue;
                }

                // Recurse if we're merging plain objects or arrays
                if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
                    if (copyIsArray) {
                        copyIsArray = false;
                        clone = src && jQuery.isArray(src) ? src : [];

                    } else {
                        clone = src && jQuery.isPlainObject(src) ? src : {};
                    }

                    // Never move original objects, clone them
                    target[name] = jQuery.extend(deep, clone, copy);

                    // Don't bring in undefined values
                } else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }

    // Return the modified object
    return target;
}

help.init({});
